/*
 * Copyright 2011 Andrew Freer
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#define INITGUID
#include "resources.h"
#include "utility.h"
#include "dxdiagcom.h"
#include <assert.h>
#include <errno.h>
#include <initguid.h>
#include <dxdiag.h>
#include <oleauto.h>
#include <oaidl.h>
#include <stdio.h>
#include <wchar.h>

typedef VOID *(*create_container) (IDxDiagContainer * iContainer);

static HRESULT GetPropStr(IDxDiagContainer * container,
                                      const char *property,
                                      WCHAR ** value);
static VOID *create_DxDiag_SystemInfo(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DisplayDevice(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectMusic(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_SoundDevice(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_SoundCaptureDevice(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectMusicPort(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DXVADeinterlaceCap(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectXFiles(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectXFile(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_SystemDevice(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectShowFilter(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_LogicalDisk(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_Driver(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectPlayAdapter(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectPlaySp(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectPlay(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectInput(IDxDiagContainer * iContainer);
static VOID *create_DxDiag_DirectInputRelatedDevice(IDxDiagContainer *
                                             iContainer);
static VOID *create_DxDiag_DirectInputDevice(IDxDiagContainer * iContainer);

HRESULT DxDiagCOM_init(IDxDiagContainer ** dxRoot)
{
    HRESULT hr;
    DXDIAG_INIT_PARAMS params;
    IDxDiagProvider *dxProvider = NULL;

    /* Initialize COM */
    hr = CoInitialize(NULL);
    if (FAILED(hr))
        return hr;

    /* Get the Dxdiag Provider */
    hr = CoCreateInstance(&CLSID_DxDiagProvider, NULL,
                          CLSCTX_INPROC_SERVER, &IID_IDxDiagProvider,
                          (LPVOID *) & dxProvider);
    if (FAILED(hr))
        return hr;

    /* Initialize the provider */
    params.dwSize = sizeof(params);
    params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
    params.bAllowWHQLChecks = TRUE;
    params.pReserved = NULL;
    hr = IDxDiagProvider_Initialize(dxProvider, &params);
    if (FAILED(hr)) {
        IDxDiagProvider_Release(dxProvider);
        return hr;
    }

    /* Get the root container */
    hr = IDxDiagProvider_GetRootContainer(dxProvider, dxRoot);
    IDxDiagProvider_Release(dxProvider);
    return hr;
}

static HRESULT GetPropStr(IDxDiagContainer * container,
                                      const char *property, WCHAR ** value)
{
    HRESULT hr;
    VARIANT var;
    INT length;
    assert(container);
    VariantInit(&var);
    length = MultiByteToWideChar(0, 0, property, -1, NULL, 0)+1;
    {
        WCHAR *propertyW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * length);
        if (!propertyW)
            return E_FAIL;

        MultiByteToWideChar(0, 0, property, -1, propertyW, length);
        hr = IDxDiagContainer_GetProp(container, propertyW, &var);
        HeapFree(GetProcessHeap(), 0, propertyW);
        if (hr != S_OK) {
            /* Set string to null */
            *value = NULL;
            return hr;
        }
        VariantChangeType(&var, &var, VARIANT_ALPHABOOL, VT_BSTR);
        *value = V_BSTR(&var);
        return hr;
    }
}

static BOOL is_number(WCHAR * text)
{
    WCHAR *end;
    lstrtolW(text, &end, 10);
    return (end != text);
}

#define MAX_CONTAINER_NAME_LEN 1024
static VOID **ParseContainers(IDxDiagContainer * iContainer,
                                  int *numContainers,
                                  create_container create)
{
    HRESULT hr;
    IDxDiagContainer *child;
    DWORD numChild;
    int i, validCount;
    WCHAR text[MAX_CONTAINER_NAME_LEN];
    VOID **containers;
    BOOL isNumber;

    assert(iContainer != NULL);

    /* Initialize num containers */
    *numContainers = 0;

    /* Get number of children */
    hr = IDxDiagContainer_GetNumberOfChildContainers(iContainer,
                                                     &numChild);
    if (hr != S_OK || numChild <= 0)
        return NULL;

    /* Allocate containers */
    containers = HeapAlloc(GetProcessHeap(), 0, (int) (numChild) * sizeof(VOID *));

    /* Iterate over children */
    validCount = 0;
    for (i = 0; i < (int) numChild; i++) {
        /* Get the child name */
        hr = IDxDiagContainer_EnumChildContainerNames(iContainer, i,
                                                      (LPWSTR)
                                                      & text,
                                                      MAX_CONTAINER_NAME_LEN);
        isNumber = is_number(text);
        if (hr != S_OK || !isNumber) {
            continue;
        }

        /* Get the child */
        hr = IDxDiagContainer_GetChildContainer(iContainer, (LPCWSTR) text,
                                                &child);
        if (hr == S_OK) {
            containers[validCount] = create(child);
            validCount++;
        }
    }

    /* Done */
    *numContainers = validCount;
    return containers;
}

static VOID *ParseContainer(IDxDiagContainer * iContainer,
                                const char *name, create_container create)
{
    HRESULT hr;
    IDxDiagContainer *child;
    INT length;

    assert(iContainer != NULL);
    assert(name != NULL);
    length = MultiByteToWideChar(0, 0, name, -1, NULL, 0)+1;
    {

        WCHAR *nameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*length);
        if (!nameW)
            return NULL;
        MultiByteToWideChar(0, 0, name, -1, nameW, length);

        /* Get child and create */
        hr = IDxDiagContainer_GetChildContainer(iContainer, nameW, &child);

        HeapFree(GetProcessHeap(), 0, nameW);

        if (hr == S_OK) {
            return create(child);
        } else {
            fprintf(stderr, "Container %s could not be found\n", name);
            return NULL;
        }

    }
}

static IDxDiagContainer *GetContainer(IDxDiagContainer * iContainer,
                                          const char *name)
{
    HRESULT hr;
    IDxDiagContainer *child;
    INT length;

    /* Sanity */
    assert(iContainer != NULL);
    assert(name != NULL);
    length = MultiByteToWideChar(0, 0, name, -1, NULL, 0)+1;
    {
        /* Allocate on the stack */
        WCHAR nameW[length];
        MultiByteToWideChar(0, 0, name, -1, nameW, length);

        /* Get child and create */
        hr = IDxDiagContainer_GetChildContainer(iContainer, nameW, &child);
        if (hr == S_OK) {
            return child;
        } else {
            fprintf(stderr, "Container %s could not be found\n", name);
            return NULL;
        }
    }
}

BOOL DxDiagCOM_ParseRoot(IDxDiagContainer * iContainer,
                       DxDiag_Root * container)
{
    IDxDiagContainer *displayDevices, *directSound, *soundDevices,
        *soundCaptureDevices, *systemDevices, *logicalDisks,
        *directShowFilters;

    /* SystemInfo */
    container->systemInfo = ParseContainer(iContainer,
                                                      "DxDiag_SystemInfo",
                                                      create_DxDiag_SystemInfo);
    if (!container->systemInfo)
        return FALSE;

    /* DisplayDevices */
    displayDevices
        = GetContainer(iContainer, "DxDiag_DisplayDevices");
    if (displayDevices == NULL) {
        container->displayDevices = NULL;
        container->numDisplayDevices = 0;
    } else {
        container->displayDevices = (DxDiag_DisplayDevice **)
            ParseContainers(displayDevices,
                                       &container->numDisplayDevices,
                                       create_DxDiag_DisplayDevice);
        if (!container->displayDevices)
            return FALSE;
    }

    /* DirectSound */
    directSound =
        GetContainer(iContainer, "DxDiag_DirectSound");
    if (directSound == NULL) {
        container->soundDevices = NULL;
        container->soundCaptureDevices = NULL;
    } else {
        /* SoundDevices */
        soundDevices = GetContainer(directSound,
                                               "DxDiag_SoundDevices");
        if (soundDevices == NULL) {
            container->soundDevices = NULL;
            container->numSoundDevices = 0;
        } else {
            container->soundDevices = (DxDiag_SoundDevice **)
                ParseContainers(soundDevices,
                                           &container->numSoundDevices,
                                           create_DxDiag_SoundDevice);
            if (!container->soundDevices)
                return FALSE;

        }

        /* SoundCaptureDevices */
        soundCaptureDevices = GetContainer(directSound,
                                                      "DxDiag_SoundCaptureDevices");
        if (soundCaptureDevices == NULL) {
            container->soundCaptureDevices = NULL;
            container->numSoundCaptureDevices = 0;
        } else {
            container->soundCaptureDevices = (DxDiag_SoundCaptureDevice **)
                ParseContainers(soundCaptureDevices,
                                           &container->numSoundCaptureDevices,
                                           create_DxDiag_SoundCaptureDevice);
            if (!container->soundCaptureDevices)
                return FALSE;
        }
    }

    /* DirectMusic */
    container->directMusic =
        (DxDiag_DirectMusic *) ParseContainer(iContainer,
                                                         "DxDiag_DirectMusic",
                                                         create_DxDiag_DirectMusic);
    if (!container->directMusic)
        return FALSE;

    /* DirectInput */
    container->directInput =
        (DxDiag_DirectInput *) ParseContainer(iContainer,
                                                         "DxDiag_DirectInput",
                                                         create_DxDiag_DirectInput);
    if (!container->directInput)
        return FALSE;

    /* DirectPlay */
    container->directPlay =
        (DxDiag_DirectPlay *) ParseContainer(iContainer,
                                                        "DxDiag_DirectPlay",
                                                        create_DxDiag_DirectPlay);

    if (!container->directPlay)
        return FALSE;

    /* SystemDevices */
    systemDevices =
        GetContainer(iContainer, "DxDiag_SystemDevices");
    if (systemDevices == NULL) {
        container->systemDevices = NULL;
        container->numSystemDevices = 0;
    } else {
        container->systemDevices = (DxDiag_SystemDevice **)
            ParseContainers(systemDevices,
                                       &container->numSystemDevices,
                                       create_DxDiag_SystemDevice);
    }

    /* DirectXFiles */
    container->directXFiles = ParseContainer(iContainer,
                                                        "DxDiag_DirectXFiles",
                                                        create_DxDiag_DirectXFiles);

    if (!container->directXFiles)
        return FALSE;

    /* DirectShowFilters */
    directShowFilters = GetContainer(iContainer,
                                                "DxDiag_DirectShowFilters");
    if (directShowFilters == NULL) {
        container->directShowFilters = NULL;
        container->numDirectShowFilters = 0;
    } else {
        container->directShowFilters = (DxDiag_DirectShowFilter **)
            ParseContainers(directShowFilters,
                                       &container->numDirectShowFilters,
                                       create_DxDiag_DirectShowFilter);
    }

    /* LogicalDisks */
    logicalDisks =
        GetContainer(iContainer, "DxDiag_LogicalDisks");
    if (logicalDisks == NULL) {
        container->logicalDisks = NULL;
        container->numLogicalDisks = 0;
    } else {
        container->logicalDisks = (DxDiag_LogicalDisk **)
            ParseContainers(logicalDisks,
                                       &container->numLogicalDisks,
                                       create_DxDiag_LogicalDisk);
    }

    return TRUE;
}

VOID *create_DxDiag_SystemInfo(IDxDiagContainer * iContainer)
{
    DxDiag_SystemInfo *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_SystemInfo));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_SystemInfo\n");
    GetPropStr(iContainer, "dwOSMajorVersion",
                                  &container->dwOSMajorVersion);
    GetPropStr(iContainer, "dwOSMinorVersion",
                                  &container->dwOSMinorVersion);
    GetPropStr(iContainer, "dwOSBuildNumber",
                                  &container->dwOSBuildNumber);
    GetPropStr(iContainer, "dwOSPlatformID",
                                  &container->dwOSPlatformID);
    GetPropStr(iContainer, "dwDirectXVersionMajor",
                                  &container->dwDirectXVersionMajor);
    GetPropStr(iContainer, "dwDirectXVersionMinor",
                                  &container->dwDirectXVersionMinor);
    GetPropStr(iContainer, "szDirectXVersionLetter",
                                  &container->szDirectXVersionLetter);
    GetPropStr(iContainer, "bDebug",
                                  &container->bDebug);
    GetPropStr(iContainer, "bNECPC98",
                                  &container->bNECPC98);
    GetPropStr(iContainer, "ullPhysicalMemory",
                                  &container->ullPhysicalMemory);
    GetPropStr(iContainer, "ullPhysicalMemoryOS",
                                  &container->ullPhysicalMemoryOS);
    GetPropStr(iContainer, "ullUsedPageFile",
                                  &container->ullUsedPageFile);
    GetPropStr(iContainer, "ullAvailPageFile",
                                  &container->ullAvailPageFile);
    GetPropStr(iContainer, "bNetMeetingRunning",
                                  &container->bNetMeetingRunning);
    GetPropStr(iContainer, "bIsD3D8DebugRuntimeAvailable",
                                  &container->bIsD3D8DebugRuntimeAvailable);
    GetPropStr(iContainer, "bIsD3DDebugRuntime",
                                  &container->bIsD3DDebugRuntime);
    GetPropStr(iContainer, "bIsDInput8DebugRuntimeAvailable",
                                  &container->bIsDInput8DebugRuntimeAvailable);
    GetPropStr(iContainer, "bIsDInput8DebugRuntime",
                                  &container->bIsDInput8DebugRuntime);
    GetPropStr(iContainer, "bIsDMusicDebugRuntimeAvailable",
                                  &container->bIsDMusicDebugRuntimeAvailable);
    GetPropStr(iContainer, "bIsDMusicDebugRuntime",
                                  &container->bIsDMusicDebugRuntime);
    GetPropStr(iContainer, "bIsDDrawDebugRuntime",
                                  &container->bIsDDrawDebugRuntime);
    GetPropStr(iContainer, "bIsDPlayDebugRuntime",
                                  &container->bIsDPlayDebugRuntime);
    GetPropStr(iContainer, "bIsDSoundDebugRuntime",
                                  &container->bIsDSoundDebugRuntime);
    GetPropStr(iContainer, "nD3DDebugLevel",
                                  &container->nD3DDebugLevel);
    GetPropStr(iContainer, "nDDrawDebugLevel",
                                  &container->nDDrawDebugLevel);
    GetPropStr(iContainer, "nDIDebugLevel",
                                  &container->nDIDebugLevel);
    GetPropStr(iContainer, "nDMusicDebugLevel",
                                  &container->nDMusicDebugLevel);
    GetPropStr(iContainer, "nDPlayDebugLevel",
                                  &container->nDPlayDebugLevel);
    GetPropStr(iContainer, "nDSoundDebugLevel",
                                  &container->nDSoundDebugLevel);
    GetPropStr(iContainer, "nDShowDebugLevel",
                                  &container->nDShowDebugLevel);
    GetPropStr(iContainer, "szWindowsDir",
                                  &container->szWindowsDir);
    GetPropStr(iContainer, "szBuildLab",
                                  &container->szBuildLab);
    GetPropStr(iContainer, "szDxDiagVersion",
                                  &container->szDxDiagVersion);
    GetPropStr(iContainer, "szSetupParamEnglish",
                                  &container->szSetupParamEnglish);
    GetPropStr(iContainer, "szProcessorEnglish",
                                  &container->szProcessorEnglish);
    GetPropStr(iContainer, "szSystemManufacturerEnglish",
                                  &container->szSystemManufacturerEnglish);
    GetPropStr(iContainer, "szSystemModelEnglish",
                                  &container->szSystemModelEnglish);
    GetPropStr(iContainer, "szBIOSEnglish",
                                  &container->szBIOSEnglish);
    GetPropStr(iContainer, "szPhysicalMemoryEnglish",
                                  &container->szPhysicalMemoryEnglish);
    GetPropStr(iContainer, "szPhysicalMemoryEnglishOS",
                                  &container->szPhysicalMemoryEnglishOS);
    GetPropStr(iContainer, "szCSDVersion",
                                  &container->szCSDVersion);
    GetPropStr(iContainer, "szUserDPI",
                                  &container->szUserDPI);
    GetPropStr(iContainer, "szSystemDPI",
                                  &container->szSystemDPI);
    GetPropStr(iContainer, "szDWMScalingDPI",
                                  &container->szDWMScalingDPI);
    GetPropStr(iContainer, "szDirectXVersionEnglish",
                                  &container->szDirectXVersionEnglish);
    GetPropStr(iContainer, "szDirectXVersionLongEnglish",
                                  &container->szDirectXVersionLongEnglish);
    GetPropStr(iContainer, "szMachineNameLocalized",
                                  &container->szMachineNameLocalized);
    GetPropStr(iContainer, "szOSLocalized",
                                  &container->szOSLocalized);
    GetPropStr(iContainer, "szOSExLocalized",
                                  &container->szOSExLocalized);
    GetPropStr(iContainer, "szOSExLongLocalized",
                                  &container->szOSExLongLocalized);
    GetPropStr(iContainer, "szLanguagesLocalized",
                                  &container->szLanguagesLocalized);
    GetPropStr(iContainer, "szPageFileLocalized",
                                  &container->szPageFileLocalized);
    GetPropStr(iContainer, "szTimeLocalized",
                                  &container->szTimeLocalized);
    GetPropStr(iContainer, "szMachineNameEnglish",
                                  &container->szMachineNameEnglish);
    GetPropStr(iContainer, "szOSEnglish",
                                  &container->szOSEnglish);
    GetPropStr(iContainer, "szOSExEnglish",
                                  &container->szOSExEnglish);
    GetPropStr(iContainer, "szOSExLongEnglish",
                                  &container->szOSExLongEnglish);
    GetPropStr(iContainer, "szLanguagesEnglish",
                                  &container->szLanguagesEnglish);
    GetPropStr(iContainer, "szPageFileEnglish",
                                  &container->szPageFileEnglish);
    GetPropStr(iContainer, "szTimeEnglish",
                                  &container->szTimeEnglish);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000009_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000009_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000009_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000009_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000009_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000009_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000009_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000009_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000a_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000a_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000a_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000a_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000a_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000a_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000a_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000a_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000b_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000b_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000b_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000b_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000b_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000b_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000b_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000b_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000c_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000c_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000c_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000c_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000c_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000c_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000c_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000c_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000d_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000d_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000d_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000d_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000d_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000d_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000d_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000d_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000e_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000e_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000e_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000e_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000e_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000e_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000e_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000e_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000f_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000f_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000f_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000f_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000f_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000f_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x8000000f_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x8000000f_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000010_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000010_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000010_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000010_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000010_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000010_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000010_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000010_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000011_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000011_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000011_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000011_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000011_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000011_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000011_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000011_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000012_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000012_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000012_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000012_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000012_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000012_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000012_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000012_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000013_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000013_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000013_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000013_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000013_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000013_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000013_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000013_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000014_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000014_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000014_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000014_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000014_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000014_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000014_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000014_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000015_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000015_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000015_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000015_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000015_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000015_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000015_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000015_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000016_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000016_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000016_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000016_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000016_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000016_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000016_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000016_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000017_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000017_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000017_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000017_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000017_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000017_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000017_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000017_bits96_127);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000018_bits0_31",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000018_bits0_31);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000018_bits32_63",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000018_bits32_63);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000018_bits64_95",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000018_bits64_95);
    GetPropStr(iContainer, "ExtendedCPUFunctionBitmasks_0x80000018_bits96_127",
                                  &container->ExtendedCPUFunctionBitmasks_0x80000018_bits96_127);
    return container;
}

VOID *create_DxDiag_DirectMusic(IDxDiagContainer * iContainer)
{
    IDxDiagContainer *directMusicPorts;
    DxDiag_DirectMusic *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectMusic));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectMusic\n");
    GetPropStr(iContainer, "bDMusicInstalled",
                                  &container->bDMusicInstalled);
    GetPropStr(iContainer, "szGMFilePath",
                                  &container->szGMFilePath);
    GetPropStr(iContainer, "szGMFileVersion",
                                  &container->szGMFileVersion);
    GetPropStr(iContainer, "bAccelerationEnabled",
                                  &container->bAccelerationEnabled);
    GetPropStr(iContainer, "bAccelerationExists",
                                  &container->bAccelerationExists);
    GetPropStr(iContainer, "szNotesLocalized",
                                  &container->szNotesLocalized);
    GetPropStr(iContainer, "szNotesEnglish",
                                  &container->szNotesEnglish);
    GetPropStr(iContainer, "szRegHelpText",
                                  &container->szRegHelpText);
    GetPropStr(iContainer, "szTestResultLocalized",
                                  &container->szTestResultLocalized);
    GetPropStr(iContainer, "szTestResultEnglish",
                                  &container->szTestResultEnglish);
    directMusicPorts = GetContainer(iContainer,
                                               "DxDiag_DirectMusicPorts");
    if (directMusicPorts == NULL) {
        container->directMusicPorts = NULL;
        container->numDirectMusicPorts = 0;
    } else {
        container->directMusicPorts = (DxDiag_DirectMusicPort **)
            ParseContainers(directMusicPorts,
                                       &container->numDirectMusicPorts,
                                       create_DxDiag_DirectMusicPort);
    }
    return container;
}

VOID *create_DxDiag_DirectInput(IDxDiagContainer * iContainer)
{
    IDxDiagContainer *directInputDevices, *directInputGameports,
        *directInputPs2Devices, *directInputUSBRoot;
    DxDiag_DirectInput *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectInput));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectInput\n");
    GetPropStr(iContainer, "bPollFlags",
                                  &container->bPollFlags);
    GetPropStr(iContainer, "szInputNotesLocalized",
                                  &container->szInputNotesLocalized);
    GetPropStr(iContainer, "szInputNotesEnglish",
                                  &container->szInputNotesEnglish);
    GetPropStr(iContainer, "szRegHelpText",
                                  &container->szRegHelpText);
    directInputDevices = GetContainer(iContainer,
                                                 "DxDiag_DirectInputDevices");
    if (directInputDevices == NULL) {
        container->directInputDevices = NULL;
        container->numDirectInputDevices = 0;
    } else {
        container->directInputDevices = (DxDiag_DirectInputDevice **)
            ParseContainers(directInputDevices,
                                       &container->numDirectInputDevices,
                                       create_DxDiag_DirectInputDevice);
    }
    directInputGameports = GetContainer(iContainer,
                                                   "DxDiag_DirectInputGameports");
    if (directInputGameports == NULL) {
        container->directInputGamePorts = NULL;
        container->numDirectInputGamePorts = 0;
    } else {
        container->directInputGamePorts
            = (DxDiag_DirectInputRelatedDevice **)
            ParseContainers(directInputGameports,
                                       &container->numDirectInputGamePorts,
                                       create_DxDiag_DirectInputRelatedDevice);
    }
    directInputUSBRoot = GetContainer(iContainer,
                                                 "DxDiag_DirectInputUSBRoot");
    if (directInputUSBRoot == NULL) {
        container->directInputUSBs = NULL;
        container->numDirectInputUSBs = 0;
    } else {
        container->directInputUSBs = (DxDiag_DirectInputRelatedDevice **)
            ParseContainers(directInputUSBRoot,
                                       &container->numDirectInputUSBs,
                                       create_DxDiag_DirectInputRelatedDevice);
    }
    directInputPs2Devices = GetContainer(iContainer,
                                                    "DxDiag_DirectInputPS2Devices");
    if (directInputPs2Devices == NULL) {
        container->directInputPs2Devices = NULL;
        container->numDirectInputPs2Devices = 0;
    } else {
        container->directInputPs2Devices
            = (DxDiag_DirectInputRelatedDevice **)
            ParseContainers(directInputPs2Devices,
                                       &container->numDirectInputPs2Devices,
                                       create_DxDiag_DirectInputRelatedDevice);
    }
    return container;
}

VOID *create_DxDiag_DirectPlay(IDxDiagContainer * iContainer)
{
    IDxDiagContainer *directPlaySps, *directPlayAdapters;
    DxDiag_DirectPlay *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectPlay));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectPlay\n");
    GetPropStr(iContainer, "szNetworkNotesLocalized",
                                  &container->szNetworkNotesLocalized);
    GetPropStr(iContainer, "szNetworkNotesEnglish",
                                  &container->szNetworkNotesEnglish);
    GetPropStr(iContainer, "szRegHelpText",
                                  &container->szRegHelpText);
    GetPropStr(iContainer, "szTestResultLocalized",
                                  &container->szTestResultLocalized);
    GetPropStr(iContainer, "szTestResultEnglish",
                                  &container->szTestResultEnglish);
    GetPropStr(iContainer, "szVoiceWizardFullDuplexTestLocalized",
                                  &container->szVoiceWizardFullDuplexTestLocalized);
    GetPropStr(iContainer, "szVoiceWizardHalfDuplexTestLocalized",
                                  &container->szVoiceWizardHalfDuplexTestLocalized);
    GetPropStr(iContainer, "szVoiceWizardMicTestLocalized",
                                  &container->szVoiceWizardMicTestLocalized);
    GetPropStr(iContainer, "szVoiceWizardFullDuplexTestEnglish",
                                  &container->szVoiceWizardFullDuplexTestEnglish);
    GetPropStr(iContainer, "szVoiceWizardHalfDuplexTestEnglish",
                                  &container->szVoiceWizardHalfDuplexTestEnglish);
    GetPropStr(iContainer, "szVoiceWizardMicTestEnglish",
                                  &container->szVoiceWizardMicTestEnglish);
    directPlayAdapters = GetContainer(iContainer, "DxDiag_DirectPlayAdapters");
    if (directPlayAdapters == NULL) {
        container->directPlayAdapters = NULL;
        container->numDirectPlayAdapters = 0;
    } else {
        container->directPlayAdapters = (DxDiag_DirectPlayAdapter **)
            ParseContainers(directPlayAdapters,
                                       &container->numDirectPlayAdapters,
                                       create_DxDiag_DirectPlayAdapter);
    }
    directPlaySps =
        GetContainer(iContainer, "DxDiag_DirectPlaySPs");
    if (directPlaySps == NULL) {
        container->directPlaySps = NULL;
        container->numDirectPlaySps = 0;
    } else {
        container->directPlaySps = (DxDiag_DirectPlaySp **)
            ParseContainers(directPlaySps,
                                       &container->numDirectPlaySps,
                                       create_DxDiag_DirectPlaySp);
    }
    return container;
}

VOID *create_DxDiag_DirectXFiles(IDxDiagContainer * iContainer)
{
    DxDiag_DirectXFiles *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectXFiles));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectXFiles\n");
    GetPropStr(iContainer, "szDXFileNotesLocalized",
                                  &container->szDXFileNotesLocalized);
    GetPropStr(iContainer, "szDXFileNotesEnglish",
                                  &container->szDXFileNotesEnglish);
    container->directXFiles =
        (DxDiag_DirectXFile **) ParseContainers(iContainer,
                                                           &container->numDirectXFiles,
                                                           create_DxDiag_DirectXFile);

    return container;
}

VOID *create_DxDiag_DirectXFile(IDxDiagContainer * iContainer)
{
    DxDiag_DirectXFile *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectXFile));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectXFile\n");
    GetPropStr(iContainer, "szName",
                                  &container->szName);
    GetPropStr(iContainer, "szVersion",
                                  &container->szVersion);
    GetPropStr(iContainer, "szLanguageEnglish",
                                  &container->szLanguageEnglish);
    GetPropStr(iContainer, "szLanguageLocalized",
                                  &container->szLanguageLocalized);
    GetPropStr(iContainer, "dwFileTimeLow",
                                  &container->dwFileTimeLow);
    GetPropStr(iContainer, "dwFileTimeHigh",
                                  &container->dwFileTimeHigh);
    GetPropStr(iContainer, "szDatestampEnglish",
                                  &container->szDatestampEnglish);
    GetPropStr(iContainer, "szDatestampLocalized",
                                  &container->szDatestampLocalized);
    GetPropStr(iContainer, "szAttributes",
                                  &container->szAttributes);
    GetPropStr(iContainer, "lNumBytes",
                                  &container->lNumBytes);
    GetPropStr(iContainer, "bExists",
                                  &container->bExists);
    GetPropStr(iContainer, "bBeta", &container->bBeta);
    GetPropStr(iContainer, "bDebug",
                                  &container->bDebug);
    GetPropStr(iContainer, "bObsolete",
                                  &container->bObsolete);
    GetPropStr(iContainer, "bProblem",
                                  &container->bProblem);
    return container;
}

VOID *create_DxDiag_DirectPlayAdapter(IDxDiagContainer * iContainer)
{
    DxDiag_DirectPlayAdapter *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectPlayAdapter));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectPlayAdapter\n");
    GetPropStr(iContainer, "szAdapterName",
                                  &container->szAdapterName);
    GetPropStr(iContainer, "szSPNameEnglish",
                                  &container->szSPNameEnglish);
    GetPropStr(iContainer, "szSPNameLocalized",
                                  &container->szSPNameLocalized);
    GetPropStr(iContainer, "szGuid",
                                  &container->szGuid);
    GetPropStr(iContainer, "dwFlags",
                                  &container->dwFlags);
    return container;
}

VOID *create_DxDiag_DirectPlaySp(IDxDiagContainer * iContainer)
{
    DxDiag_DirectPlaySp *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectPlaySp));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectPlaySp\n");
    GetPropStr(iContainer, "szNameLocalized",
                                  &container->szNameLocalized);
    GetPropStr(iContainer, "szNameEnglish",
                                  &container->szNameEnglish);
    GetPropStr(iContainer, "szGuid",
                                  &container->szGuid);
    GetPropStr(iContainer, "szFile",
                                  &container->szFile);
    GetPropStr(iContainer, "szPath",
                                  &container->szPath);
    GetPropStr(iContainer, "szVersionLocalized",
                                  &container->szVersionLocalized);
    GetPropStr(iContainer, "szVersionEnglish",
                                  &container->szVersionEnglish);
    GetPropStr(iContainer, "bRegistryOK",
                                  &container->bRegistryOK);
    GetPropStr(iContainer, "bProblem",
                                  &container->bProblem);
    GetPropStr(iContainer, "bFileMissing",
                                  &container->bFileMissing);
    GetPropStr(iContainer, "bInstalled",
                                  &container->bInstalled);
    GetPropStr(iContainer, "dwDXVer",
                                  &container->dwDXVer);
    return container;
}

VOID *create_DxDiag_DirectMusicPort(IDxDiagContainer * iContainer)
{
    DxDiag_DirectMusicPort *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectMusicPort));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectMusicPort\n");
    GetPropStr(iContainer, "szGuid",
                                  &container->szGuid);
    GetPropStr(iContainer, "bSoftware",
                                  &container->bSoftware);
    GetPropStr(iContainer, "bKernelMode",
                                  &container->bKernelMode);
    GetPropStr(iContainer, "bUsesDLS",
                                  &container->bUsesDLS);
    GetPropStr(iContainer, "bExternal",
                                  &container->bExternal);
    GetPropStr(iContainer, "dwMaxAudioChannels",
                                  &container->dwMaxAudioChannels);
    GetPropStr(iContainer, "dwMaxChannelGroups",
                                  &container->dwMaxChannelGroups);
    GetPropStr(iContainer, "bDefaultPort",
                                  &container->bDefaultPort);
    GetPropStr(iContainer, "bOutputPort",
                                  &container->bOutputPort);
    GetPropStr(iContainer, "szDescription",
                                  &container->szDescription);
    return container;
}

VOID *create_DxDiag_LogicalDisk(IDxDiagContainer * iContainer)
{
    IDxDiagContainer *drivers;
    DxDiag_LogicalDisk *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_LogicalDisk));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_LogicalDisk\n");
    GetPropStr(iContainer, "szDriveLetter",
                                  &container->szDriveLetter);
    GetPropStr(iContainer, "szFreeSpace",
                                  &container->szFreeSpace);
    GetPropStr(iContainer, "szMaxSpace",
                                  &container->szMaxSpace);
    GetPropStr(iContainer, "szFileSystem",
                                  &container->szFileSystem);
    GetPropStr(iContainer, "szModel",
                                  &container->szModel);
    GetPropStr(iContainer, "szPNPDeviceID",
                                  &container->szPNPDeviceID);
    GetPropStr(iContainer, "dwHardDriveIndex",
                                  &container->dwHardDriveIndex);
    drivers = GetContainer(iContainer, "Drivers");
    if (drivers == NULL) {
        container->drivers = NULL;
        container->numDrivers = 0;
    } else {
        container->drivers =
            (DxDiag_Driver **) ParseContainers(drivers,
                                                          &container->numDrivers,
                                                          create_DxDiag_Driver);
    }
    return container;
}

VOID *create_DxDiag_SystemDevice(IDxDiagContainer * iContainer)
{
    IDxDiagContainer *drivers;
    DxDiag_SystemDevice *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_SystemDevice));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_SystemDevice\n");
    GetPropStr(iContainer, "szDescription",
                                  &container->szDescription);
    GetPropStr(iContainer, "szDeviceID",
                                  &container->szDeviceID);
    drivers = GetContainer(iContainer, "Drivers");
    if (drivers == NULL) {
        container->drivers = NULL;
        container->numDrivers = 0;
    } else {
        container->drivers =
            (DxDiag_Driver **) ParseContainers(drivers,
                                                          &container->numDrivers,
                                                          create_DxDiag_Driver);
    }
    return container;
}

VOID *create_DxDiag_Driver(IDxDiagContainer * iContainer)
{
    DxDiag_Driver *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_Driver));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_Driver\n");
    GetPropStr(iContainer, "szPath",
                                  &container->szPath);
    GetPropStr(iContainer, "szName",
                                  &container->szName);
    GetPropStr(iContainer, "szVersion",
                                  &container->szVersion);
    GetPropStr(iContainer, "szLanguageEnglish",
                                  &container->szLanguageEnglish);
    GetPropStr(iContainer, "szLanguageLocalized",
                                  &container->szLanguageLocalized);
    GetPropStr(iContainer, "dwFileTimeLow",
                                  &container->dwFileTimeLow);
    GetPropStr(iContainer, "dwFileTimeHigh",
                                  &container->dwFileTimeHigh);
    GetPropStr(iContainer, "szDatestampEnglish",
                                  &container->szDatestampEnglish);
    GetPropStr(iContainer, "szDatestampLocalized",
                                  &container->szDatestampLocalized);
    GetPropStr(iContainer, "szAttributes",
                                  &container->szAttributes);
    GetPropStr(iContainer, "lNumBytes",
                                  &container->lNumBytes);
    GetPropStr(iContainer, "bExists",
                                  &container->bExists);
    GetPropStr(iContainer, "bBeta", &container->bBeta);
    GetPropStr(iContainer, "bDebug",
                                  &container->bDebug);
    GetPropStr(iContainer, "bObsolete",
                                  &container->bObsolete);
    GetPropStr(iContainer, "bProblem",
                                  &container->bProblem);
    return container;
}

VOID *create_DxDiag_DirectShowFilter(IDxDiagContainer * iContainer)
{
    DxDiag_DirectShowFilter *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectShowFilter));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectShowFilter\n");
    GetPropStr(iContainer, "szName",
                                  &container->szName);
    GetPropStr(iContainer, "szVersion",
                                  &container->szVersion);
    GetPropStr(iContainer, "ClsidFilter",
                                  &container->ClsidFilter);
    GetPropStr(iContainer, "szFileName",
                                  &container->szFileName);
    GetPropStr(iContainer, "szFileVersion",
                                  &container->szFileVersion);
    GetPropStr(iContainer, "szCatName",
                                  &container->szCatName);
    GetPropStr(iContainer, "ClsidCat",
                                  &container->ClsidCat);
    GetPropStr(iContainer, "dwInputs",
                                  &container->dwInputs);
    GetPropStr(iContainer, "dwOutputs",
                                  &container->dwOutputs);
    GetPropStr(iContainer, "dwMerit",
                                  &container->dwMerit);
    return container;
}

static VOID *create_DxDiag_DirectInputRelatedDevice(IDxDiagContainer * iContainer)
{
    IDxDiagContainer *drivers;
    DxDiag_DirectInputRelatedDevice *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectInputRelatedDevice));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectInputRelatedDevice\n");
    GetPropStr(iContainer, "dwVendorID",
                                  &container->dwVendorID);
    GetPropStr(iContainer, "dwProductID",
                                  &container->dwProductID);
    GetPropStr(iContainer, "szDescription",
                                  &container->szDescription);
    GetPropStr(iContainer, "szLocation",
                                  &container->szLocation);
    GetPropStr(iContainer, "szMatchingDeviceId",
                                  &container->szMatchingDeviceId);
    GetPropStr(iContainer, "szUpperFilters",
                                  &container->szUpperFilters);
    GetPropStr(iContainer, "szService",
                                  &container->szService);
    GetPropStr(iContainer, "szLowerFilters",
                                  &container->szLowerFilters);
    GetPropStr(iContainer, "szOEMData",
                                  &container->szOEMData);
    GetPropStr(iContainer, "szFlags1",
                                  &container->szFlags1);
    GetPropStr(iContainer, "szFlags2",
                                  &container->szFlags2);
    drivers = GetContainer(iContainer, "Drivers");
    if (drivers == NULL) {
        container->drivers = NULL;
        container->numDrivers = 0;
    } else {
        container->drivers =
            (DxDiag_Driver **) ParseContainers(drivers,
                                                          &container->numDrivers,
                                                          create_DxDiag_Driver);
    }
    container->directInputRelatedDevices
        = (DxDiag_DirectInputRelatedDevice **)
        ParseContainers(iContainer,
                                   &container->numDirectInputRelatedDevices,
                                   create_DxDiag_DirectInputRelatedDevice);
    return container;
}

static VOID *create_DxDiag_DirectInputDevice(IDxDiagContainer * iContainer)
{
    DxDiag_DirectInputDevice *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DirectInputDevice));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DirectInputDevice\n");
    GetPropStr(iContainer, "szInstanceName",
                                  &container->szInstanceName);
    GetPropStr(iContainer, "bAttached",
                                  &container->bAttached);
    GetPropStr(iContainer, "dwJoystickID",
                                  &container->dwJoystickID);
    GetPropStr(iContainer, "dwVendorID",
                                  &container->dwVendorID);
    GetPropStr(iContainer, "dwProductID",
                                  &container->dwProductID);
    GetPropStr(iContainer, "dwDevType",
                                  &container->dwDevType);
    GetPropStr(iContainer, "szFFDriverName",
                                  &container->szFFDriverName);
    GetPropStr(iContainer, "szFFDriverDateEnglish",
                                  &container->szFFDriverDateEnglish);
    GetPropStr(iContainer, "szFFDriverVersion",
                                  &container->szFFDriverVersion);
    GetPropStr(iContainer, "lFFDriverSize",
                                  &container->lFFDriverSize);
    return container;
}

static VOID *create_DxDiag_DisplayDevice(IDxDiagContainer * iContainer)
{
    IDxDiagContainer *dxvaDinterlaceCaps;
    DxDiag_DisplayDevice *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DisplayDevice));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DisplayDevice\n");
    GetPropStr(iContainer, "szDeviceName",
                                  &container->szDeviceName);
    GetPropStr(iContainer, "szDescription",
                                  &container->szDescription);
    GetPropStr(iContainer, "szKeyDeviceID",
                                  &container->szKeyDeviceID);
    GetPropStr(iContainer, "szKeyDeviceKey",
                                  &container->szKeyDeviceKey);
    GetPropStr(iContainer, "szManufacturer",
                                  &container->szManufacturer);
    GetPropStr(iContainer, "szChipType",
                                  &container->szChipType);
    GetPropStr(iContainer, "szDACType",
                                  &container->szDACType);
    GetPropStr(iContainer, "szRevision",
                                  &container->szRevision);
    GetPropStr(iContainer, "szDisplayMemoryLocalized",
                                  &container->szDisplayMemoryLocalized);
    GetPropStr(iContainer, "szDisplayMemoryEnglish",
                                  &container->szDisplayMemoryEnglish);
    GetPropStr(iContainer, "szDisplayModeLocalized",
                                  &container->szDisplayModeLocalized);
    GetPropStr(iContainer, "szDisplayModeEnglish",
                                  &container->szDisplayModeEnglish);
    GetPropStr(iContainer, "szOverlayEnglish",
                                  &container->szOverlayEnglish);
    GetPropStr(iContainer, "szDXVAHDEnglish",
                                  &container->szDXVAHDEnglish);
    GetPropStr(iContainer, "dwWidth",
                                  &container->dwWidth);
    GetPropStr(iContainer, "dwHeight",
                                  &container->dwHeight);
    GetPropStr(iContainer, "dwBpp", &container->dwBpp);
    GetPropStr(iContainer, "dwRefreshRate",
                                  &container->dwRefreshRate);
    GetPropStr(iContainer, "szMonitorName",
                                  &container->szMonitorName);
    GetPropStr(iContainer, "szMonitorMaxRes",
                                  &container->szMonitorMaxRes);
    GetPropStr(iContainer, "szDriverName",
                                  &container->szDriverName);
    GetPropStr(iContainer, "szDriverAssemblyVersion",
                                  &container->szDriverAssemblyVersion);
    GetPropStr(iContainer, "szDriverVersion",
                                  &container->szDriverVersion);
    GetPropStr(iContainer, "szDriverAttributes",
                                  &container->szDriverAttributes);
    GetPropStr(iContainer, "szDriverLanguageEnglish",
                                  &container->szDriverLanguageEnglish);
    GetPropStr(iContainer, "szDriverLanguageLocalized",
                                  &container->szDriverLanguageLocalized);
    GetPropStr(iContainer, "szDriverDateEnglish",
                                  &container->szDriverDateEnglish);
    GetPropStr(iContainer, "szDriverDateLocalized",
                                  &container->szDriverDateLocalized);
    GetPropStr(iContainer, "lDriverSize",
                                  &container->lDriverSize);
    GetPropStr(iContainer, "szMiniVdd",
                                  &container->szMiniVdd);
    GetPropStr(iContainer, "szMiniVddDateLocalized",
                                  &container->szMiniVddDateLocalized);
    GetPropStr(iContainer, "szMiniVddDateEnglish",
                                  &container->szMiniVddDateEnglish);
    GetPropStr(iContainer, "lMiniVddSize",
                                  &container->lMiniVddSize);
    GetPropStr(iContainer, "szVdd", &container->szVdd);
    GetPropStr(iContainer, "szDriverModelEnglish",
                                  &container->szDriverModelEnglish);
    GetPropStr(iContainer, "szDriverModelLocalized",
                                  &container->szDriverModelLocalized);
    GetPropStr(iContainer, "szDriverNodeStrongName",
                                  &container->szDriverNodeStrongName);
    GetPropStr(iContainer, "szRankOfInstalledDriver",
                                  &container->szRankOfInstalledDriver);
    GetPropStr(iContainer, "bCanRenderWindow",
                                  &container->bCanRenderWindow);
    GetPropStr(iContainer, "bDriverBeta",
                                  &container->bDriverBeta);
    GetPropStr(iContainer, "bDriverDebug",
                                  &container->bDriverDebug);
    GetPropStr(iContainer, "bDriverSigned",
                                  &container->bDriverSigned);
    GetPropStr(iContainer, "bDriverSignedValid",
                                  &container->bDriverSignedValid);
    GetPropStr(iContainer, "szDeviceIdentifier",
                                  &container->szDeviceIdentifier);
    GetPropStr(iContainer, "szDriverSignDate",
                                  &container->szDriverSignDate);
    GetPropStr(iContainer, "dwDDIVersion",
                                  &container->dwDDIVersion);
    GetPropStr(iContainer, "szDDIVersionEnglish",
                                  &container->szDDIVersionEnglish);
    GetPropStr(iContainer, "szDDIVersionLocalized",
                                  &container->szDDIVersionLocalized);
    GetPropStr(iContainer, "iAdapter",
                                  &container->iAdapter);
    GetPropStr(iContainer, "szVendorId",
                                  &container->szVendorId);
    GetPropStr(iContainer, "szDeviceId",
                                  &container->szDeviceId);
    GetPropStr(iContainer, "szSubSysId",
                                  &container->szSubSysId);
    GetPropStr(iContainer, "szRevisionId",
                                  &container->szRevisionId);
    GetPropStr(iContainer, "dwWHQLLevel",
                                  &container->dwWHQLLevel);
    GetPropStr(iContainer, "bNoHardware",
                                  &container->bNoHardware);
    GetPropStr(iContainer, "bDDAccelerationEnabled",
                                  &container->bDDAccelerationEnabled);
    GetPropStr(iContainer, "b3DAccelerationExists",
                                  &container->b3DAccelerationExists);
    GetPropStr(iContainer, "b3DAccelerationEnabled",
                                  &container->b3DAccelerationEnabled);
    GetPropStr(iContainer, "bAGPEnabled",
                                  &container->bAGPEnabled);
    GetPropStr(iContainer, "bAGPExists",
                                  &container->bAGPExists);
    GetPropStr(iContainer, "bAGPExistenceValid",
                                  &container->bAGPExistenceValid);
    GetPropStr(iContainer, "szDXVAModes",
                                  &container->szDXVAModes);
    GetPropStr(iContainer, "szDDStatusLocalized",
                                  &container->szDDStatusLocalized);
    GetPropStr(iContainer, "szDDStatusEnglish",
                                  &container->szDDStatusEnglish);
    GetPropStr(iContainer, "szD3DStatusLocalized",
                                  &container->szD3DStatusLocalized);
    GetPropStr(iContainer, "szD3DStatusEnglish",
                                  &container->szD3DStatusEnglish);
    GetPropStr(iContainer, "szAGPStatusLocalized",
                                  &container->szAGPStatusLocalized);
    GetPropStr(iContainer, "szAGPStatusEnglish",
                                  &container->szAGPStatusEnglish);
    GetPropStr(iContainer, "szNotesLocalized",
                                  &container->szNotesLocalized);
    GetPropStr(iContainer, "szNotesEnglish",
                                  &container->szNotesEnglish);
    GetPropStr(iContainer, "szRegHelpText",
                                  &container->szRegHelpText);
    GetPropStr(iContainer, "szTestResultDDLocalized",
                                  &container->szTestResultDDLocalized);
    GetPropStr(iContainer, "szTestResultDDEnglish",
                                  &container->szTestResultDDEnglish);
    GetPropStr(iContainer, "szTestResultD3D7Localized",
                                  &container->szTestResultD3D7Localized);
    GetPropStr(iContainer, "szTestResultD3D7English",
                                  &container->szTestResultD3D7English);
    GetPropStr(iContainer, "szTestResultD3D8Localized",
                                  &container->szTestResultD3D8Localized);
    GetPropStr(iContainer, "szTestResultD3D8English",
                                  &container->szTestResultD3D8English);
    GetPropStr(iContainer, "szTestResultD3D9Localized",
                                  &container->szTestResultD3D9Localized);
    GetPropStr(iContainer, "szTestResultD3D9English",
                                  &container->szTestResultD3D9English);
    dxvaDinterlaceCaps =
        GetContainer(iContainer, "DXVADeinterlaceCaps");
    if (dxvaDinterlaceCaps == NULL) {
        container->dxvaDeinterlaceCaps = NULL;
        container->numDxvaDeinterlaceCaps = 0;
    } else {
        container->dxvaDeinterlaceCaps = (DxDiag_DXVADeinterlaceCap **)
            ParseContainers(dxvaDinterlaceCaps,
                                       &container->numDxvaDeinterlaceCaps,
                                       create_DxDiag_DXVADeinterlaceCap);
    }
    return container;
}

static VOID *create_DxDiag_DXVADeinterlaceCap(IDxDiagContainer * iContainer)
{
    DxDiag_DXVADeinterlaceCap *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_DXVADeinterlaceCap));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_DXVADeinterlaceCap\n");
    GetPropStr(iContainer, "szD3DInputFormat",
                                  &container->szD3DInputFormat);
    GetPropStr(iContainer, "szD3DOutputFormat",
                                  &container->szD3DOutputFormat);
    GetPropStr(iContainer, "szGuid",
                                  &container->szGuid);
    GetPropStr(iContainer, "szCaps",
                                  &container->szCaps);
    GetPropStr(iContainer, "dwNumPreviousOutputFrames",
                                  &container->dwNumPreviousOutputFrames);
    GetPropStr(iContainer, "dwNumForwardRefSamples",
                                  &container->dwNumForwardRefSamples);
    GetPropStr(iContainer, "dwNumBackwardRefSamples",
                                  &container->dwNumBackwardRefSamples);
    return container;
}

static VOID *create_DxDiag_SoundCaptureDevice(IDxDiagContainer * iContainer)
{
    DxDiag_SoundCaptureDevice *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_SoundCaptureDevice));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_SoundCaptureDevice\n");
    GetPropStr(iContainer, "szDescription",
                                  &container->szDescription);
    GetPropStr(iContainer, "szGuidDeviceID",
                                  &container->szGuidDeviceID);
    GetPropStr(iContainer, "szDriverName",
                                  &container->szDriverName);
    GetPropStr(iContainer, "szDriverPath",
                                  &container->szDriverPath);
    GetPropStr(iContainer, "szDriverVersion",
                                  &container->szDriverVersion);
    GetPropStr(iContainer, "szDriverLanguageEnglish",
                                  &container->szDriverLanguageEnglish);
    GetPropStr(iContainer, "szDriverLanguageLocalized",
                                  &container->szDriverLanguageLocalized);
    GetPropStr(iContainer, "szDriverAttributes",
                                  &container->szDriverAttributes);
    GetPropStr(iContainer, "szDriverDateEnglish",
                                  &container->szDriverDateEnglish);
    GetPropStr(iContainer, "szDriverDateLocalized",
                                  &container->szDriverDateLocalized);
    GetPropStr(iContainer, "lNumBytes",
                                  &container->lNumBytes);
    GetPropStr(iContainer, "bDriverBeta",
                                  &container->bDriverBeta);
    GetPropStr(iContainer, "bDriverDebug",
                                  &container->bDriverDebug);
    GetPropStr(iContainer, "bDefaultSoundRecording",
                                  &container->bDefaultSoundRecording);
    GetPropStr(iContainer, "bDefaultVoiceRecording",
                                  &container->bDefaultVoiceRecording);
    GetPropStr(iContainer, "dwFlags",
                                  &container->dwFlags);
    GetPropStr(iContainer, "dwFormats",
                                  &container->dwFormats);
    return container;
}

static VOID *create_DxDiag_SoundDevice(IDxDiagContainer * iContainer)
{
    DxDiag_SoundDevice *container;
    container = HeapAlloc(GetProcessHeap(), 0, sizeof(DxDiag_SoundDevice));

    if (!container)
        return NULL;

    fprintf(stderr, "create_DxDiag_SoundDevice\n");
    GetPropStr(iContainer, "dwDevnode",
                                  &container->dwDevnode);
    GetPropStr(iContainer, "szGuidDeviceID",
                                  &container->szGuidDeviceID);
    GetPropStr(iContainer, "szHardwareID",
                                  &container->szHardwareID);
    GetPropStr(iContainer, "szRegKey",
                                  &container->szRegKey);
    GetPropStr(iContainer, "szManufacturerID",
                                  &container->szManufacturerID);
    GetPropStr(iContainer, "szProductID",
                                  &container->szProductID);
    GetPropStr(iContainer, "szDescription",
                                  &container->szDescription);
    GetPropStr(iContainer, "szDriverName",
                                  &container->szDriverName);
    GetPropStr(iContainer, "szDriverPath",
                                  &container->szDriverPath);
    GetPropStr(iContainer, "szDriverVersion",
                                  &container->szDriverVersion);
    GetPropStr(iContainer, "szDriverLanguageEnglish",
                                  &container->szDriverLanguageEnglish);
    GetPropStr(iContainer, "szDriverLanguageLocalized",
                                  &container->szDriverLanguageLocalized);
    GetPropStr(iContainer, "szDriverAttributes",
                                  &container->szDriverAttributes);
    GetPropStr(iContainer, "szDriverDateEnglish",
                                  &container->szDriverDateEnglish);
    GetPropStr(iContainer, "szDriverDateLocalized",
                                  &container->szDriverDateLocalized);
    GetPropStr(iContainer, "szOtherDrivers",
                                  &container->szOtherDrivers);
    GetPropStr(iContainer, "szProvider",
                                  &container->szProvider);
    GetPropStr(iContainer, "szType",
                                  &container->szType);
    GetPropStr(iContainer, "lNumBytes",
                                  &container->lNumBytes);
    GetPropStr(iContainer, "bDriverBeta",
                                  &container->bDriverBeta);
    GetPropStr(iContainer, "bDriverDebug",
                                  &container->bDriverDebug);
    GetPropStr(iContainer, "bDriverSigned",
                                  &container->bDriverSigned);
    GetPropStr(iContainer, "bDriverSignedValid",
                                  &container->bDriverSignedValid);
    GetPropStr(iContainer, "lAccelerationLevel",
                                  &container->lAccelerationLevel);
    GetPropStr(iContainer, "bAudioDisabled",
                                  &container->bAudioDisabled);
    GetPropStr(iContainer, "bDefaultSoundPlayback",
                                  &container->bDefaultSoundPlayback);
    GetPropStr(iContainer, "bDefaultVoicePlayback",
                                  &container->bDefaultVoicePlayback);
    GetPropStr(iContainer, "bVoiceManager",
                                  &container->bVoiceManager);
    GetPropStr(iContainer, "bEAX20Listener",
                                  &container->bEAX20Listener);
    GetPropStr(iContainer, "bEAX20Source",
                                  &container->bEAX20Source);
    GetPropStr(iContainer, "bI3DL2Listener",
                                  &container->bI3DL2Listener);
    GetPropStr(iContainer, "bI3DL2Source",
                                  &container->bI3DL2Source);
    GetPropStr(iContainer, "bZoomFX",
                                  &container->bZoomFX);
    GetPropStr(iContainer, "dwFlags",
                                  &container->dwFlags);
    GetPropStr(iContainer, "dwMinSecondarySampleRate",
                                  &container->dwMinSecondarySampleRate);
    GetPropStr(iContainer, "dwMaxSecondarySampleRate",
                                  &container->dwMaxSecondarySampleRate);
    GetPropStr(iContainer, "dwPrimaryBuffers",
                                  &container->dwPrimaryBuffers);
    GetPropStr(iContainer, "dwMaxHwMixingAllBuffers",
                                  &container->dwMaxHwMixingAllBuffers);
    GetPropStr(iContainer, "dwMaxHwMixingStaticBuffers",
                                  &container->dwMaxHwMixingStaticBuffers);
    GetPropStr(iContainer, "dwMaxHwMixingStreamingBuffers",
                                  &container->dwMaxHwMixingStreamingBuffers);
    GetPropStr(iContainer, "dwFreeHwMixingAllBuffers",
                                  &container->dwFreeHwMixingAllBuffers);
    GetPropStr(iContainer, "dwFreeHwMixingStaticBuffers",
                                  &container->dwFreeHwMixingStaticBuffers);
    GetPropStr(iContainer, "dwFreeHwMixingStreamingBuffers",
                                  &container->dwFreeHwMixingStreamingBuffers);
    GetPropStr(iContainer, "dwMaxHw3DAllBuffers",
                                  &container->dwMaxHw3DAllBuffers);
    GetPropStr(iContainer, "dwMaxHw3DStaticBuffers",
                                  &container->dwMaxHw3DStaticBuffers);
    GetPropStr(iContainer, "dwMaxHw3DStreamingBuffers",
                                  &container->dwMaxHw3DStreamingBuffers);
    GetPropStr(iContainer, "dwFreeHw3DAllBuffers",
                                  &container->dwFreeHw3DAllBuffers);
    GetPropStr(iContainer, "dwFreeHw3DStaticBuffers",
                                  &container->dwFreeHw3DStaticBuffers);
    GetPropStr(iContainer, "dwFreeHw3DStreamingBuffers",
                                  &container->dwFreeHw3DStreamingBuffers);
    GetPropStr(iContainer, "dwTotalHwMemBytes",
                                  &container->dwTotalHwMemBytes);
    GetPropStr(iContainer, "dwFreeHwMemBytes",
                                  &container->dwFreeHwMemBytes);
    GetPropStr(iContainer, "dwMaxContigFreeHwMemBytes",
                                  &container->dwMaxContigFreeHwMemBytes);
    GetPropStr(iContainer, "dwUnlockTransferRateHwBuffers",
                                  &container->dwUnlockTransferRateHwBuffers);
    GetPropStr(iContainer, "dwPlayCpuOverheadSwBuffers",
                                  &container->dwPlayCpuOverheadSwBuffers);
    GetPropStr(iContainer, "szNotesLocalized",
                                  &container->szNotesLocalized);
    GetPropStr(iContainer, "szNotesEnglish",
                                  &container->szNotesEnglish);
    GetPropStr(iContainer, "szRegHelpText",
                                  &container->szRegHelpText);
    GetPropStr(iContainer, "szTestResultLocalized",
                                  &container->szTestResultLocalized);
    GetPropStr(iContainer, "szTestResultEnglish",
                                  &container->szTestResultEnglish);
    return container;
}
